<template>
  <input
    ref="fileEle"
    class="img-upload"
    type="file"
    accept="image/*"
    @change="handleToFiles"
    multiple
  />
  <slot></slot>
</template>

<script lang="ts" setup>
import { ref } from "@vue/runtime-core";
import { ElMessage } from "element-plus";
import { dataURItoBlob, blobToBase64 } from "@/plugins/pictureProcess";
import { compress } from "image-conversion";

const emits = defineEmits<{
  (e: "change", imgs: string[]): void;
}>();

// 给input属性一个ref属性
let fileEle = ref<HTMLInputElement>();

/**
 * 准备上传图片(打开windows文件接口)
 */
const uploadImg: () => void = (): void => fileEle.value?.click();

defineExpose({
  uploadImg,
});

// 监听用户是否已经上传了图片
const handleToFiles: () => void = (): void => {
  const fileList: FileList = fileEle.value?.files as FileList;
  if (!fileList.length) return;
  const is12M = Array.from(fileList).every((item) => item.size / 1024 / 1024 < 12); // 判断文件的大小是否小于12MB
  if (!is12M) {
    // 如果大于12MB则报错直接返回
    ElMessage({
      type: "error",
      message: "上传的图片大小不能大于12MB",
    });
    return;
  }
  const imgs: Array<string> = [];
  new Promise<boolean>((resolve) => {
    Array.from(fileList).forEach((item, index) => {
      /**
       * 读取文件内容
       */
      const reader: FileReader = new FileReader();
      // 该事件在读取操作完成时触发。
      reader.onload = async (e: ProgressEvent<FileReader>) => {
        const img: string = e.target?.result as string;
        let imgBlob: Blob = dataURItoBlob(img);
        // 如果图片大于0.5MB的话则压缩图片
        if (item.size / 1024 / 1024 > 0.5) {
          // const value: Blob = await pictureCompression(img, { quality: 0.25 });
          const value: Blob = await compress(item, 0.25);
          imgBlob = value;
        }
        blobToBase64(imgBlob, (url: string) => {
          imgs.push(url);
          if (index === fileList.length - 1) resolve(true);
        });
      };
      // 读取指定的Blob或File对象
      reader.readAsDataURL(item);
    });
  }).then((value) => {
    if (value) emits("change", imgs);
    fileEle.value!.files = null;
  });
};
</script>

<style lang="scss" scoped>
.img {
  &-upload {
    display: none;
  }
}
</style>
